package st.learnopengl.apps.basic

import glm_.mat4x4.Mat4
import glm_.vec3.Vec3
import glm_.vec4.Vec4
import gln.*
import gln.draw.DrawMode
import gln.draw.glDrawArrays
import gln.glf.VertexAttribute
import gln.identifiers.GlBuffer
import gln.identifiers.GlProgram
import gln.identifiers.GlTexture
import gln.vertexArray.GlVertexArray
import gln.vertexArray.glGenVertexArray
import st.learnopengl.common.App
import st.learnopengl.common.GLUT
import org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT
import org.lwjgl.opengl.GL11.glClear
import org.lwjgl.opengl.GL13.GL_TEXTURE0
import org.lwjgl.opengl.GL13.glActiveTexture
import org.lwjgl.opengl.GL15

class Transforms(width: Int, height: Int, title: String) : App(width, height, title) {
    private var program: GlProgram? = null
    private var sample1Location : Int = -1
    private var matrixLocation: Int = -1
    private var vao: GlVertexArray? = null
    private var vbo: GlBuffer? = null
    private var texture1: GlTexture? = null
    private var rotate = 0.0f

    private lateinit var vertexAttr: VertexAttribute
    private lateinit var uvAttr: VertexAttribute

    override fun onInit() {
        program = GLUT.createProgram("shaders/transform/vertexShader.glsl"
            , "shaders/transform/fragmentShader.glsl")
        sample1Location = program!!.getUniformLocation("ourTexture1")
        matrixLocation = program!!.getUniformLocation("transform")

        vao = GlVertexArray(glGenVertexArray())
        vao!!.bound {
            vbo = GlBuffer(GL15.glGenBuffers())
            vbo!!.bound(BufferTarget.ARRAY) {
                val vertexs = floatArrayOf(
                    // positions           // texture coords
                    0.5f,  0.5f, 0.0f,    1.0f, 1.0f,   // top right
                    0.5f, -0.5f, 0.0f,    1.0f, 0.0f,   // bottom right
                    -0.5f, -0.5f, 0.0f,   0.0f, 0.0f,   // bottom left
                    -0.5f,  0.5f, 0.0f,   0.0f, 1.0f    // top left
                )
                data(vertexs, Usage.STATIC_DRAW)
            }
        }

        vertexAttr = VertexAttribute(0, 3, VertexAttrType.FLOAT
            , false, 5 * 4, 0)

        uvAttr = VertexAttribute(1, 2, VertexAttrType.FLOAT, false
            , 5 * 4, 3 * 4)

        texture1 = GLUT.loadTexture("textures/brickwall.jpg")

        glClearColor(Vec4(0.3, 0.4, 0.5, 1.0))
    }

    override fun loop() {
        glClear(GL_COLOR_BUFFER_BIT)

        program!!.use()

        vao!!.bind()

        vbo!!.bind(BufferTarget.ARRAY)

        texture1!!.bind(TextureTarget._2D)
        glActiveTexture(GL_TEXTURE0)

        program!!.programUniform(sample1Location, 0)

        var m = Mat4(1)
        m = m.translate(0.5f, -0.5f, 0.0f)
        m = m.scale(Vec3(0.5f, 0.5f, 1.0f))
        rotate += 0.01f
        m = m.rotate(rotate, 0f, 0f, 1f)
        program!!.programUniform(matrixLocation, m)

        vertexAttr.enable()
        vertexAttr.pointer()

        uvAttr.enable()
        uvAttr.pointer()

        glDrawArrays(DrawMode.TRIANGLE_FAN, 4)
    }


    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            Transforms(1280, 720, "Transform").run()
        }
    }
}